using System;
using System.Collections.Generic;
using System.Web.Mvc;
using GiveCampWeb.Models;

namespace GiveCampWeb.Controllers
{
    public class VolunteerController : Controller
    {
        public ActionResult Index()
        {
            return View("Landing");
        }

        public ActionResult SignUp()
        {
            return View("SignUp", new SignUpViewModel());
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SignUp(Volunteer volunteer, FormCollection form)
        {
            var jobRoles = SelectedJobRoles(form);
            var technologies = SelectedTechnologies(form);

            Validate(volunteer, jobRoles, technologies);

            if (ModelState.IsValid)
            {
                var volunteerRepository = new VolunteerRepository();

                volunteerRepository.Register(volunteer, jobRoles, technologies);
                volunteerRepository.Save();
                return View("Confirm");
            }

            return View(new SignUpViewModel(volunteer));
        }

        private static List<JobRole> SelectedJobRoles(FormCollection form)
        {
            var jobRoles = new List<JobRole>();
            foreach (var key in form.Keys)
            {
                if (key.ToString().StartsWith("JobType."))
                {
                    var value = form[key.ToString()];
                    bool selected = false;
                    if (value.ToLowerInvariant() == "true")
                        selected = true;
                    if (HasChanged(value) && GetNewBooleanValue(value))
                        selected = true;

                    if (selected)
                    {
                        var id = ExtractId(key.ToString());
                        var repo = new LookupRepository();
                        jobRoles.Add(repo.GetJobRole(id));
                    }
                }
            }
            return jobRoles;
        }

        private static List<Technology> SelectedTechnologies(FormCollection form)
        {
            var technologies = new List<Technology>();
            foreach (var key in form.Keys)
            {
                if (key.ToString().StartsWith("Technology."))
                {
                    var value = form[key.ToString()];
                    bool selected = false;

                    if (value.ToLowerInvariant() == "true")
                        selected = true;
                    if (HasChanged(value) && GetNewBooleanValue(value))
                        selected = true;

                    if (selected)
                    {
                        var id = ExtractId(key.ToString());
                        var repo = new LookupRepository();
                        technologies.Add(repo.GetTechnology(id));
                    }
                }
            }
            return technologies;
        }

        private static bool HasChanged(string value)
        {
            return value.Contains(",");
        }

        private static bool GetNewBooleanValue(string value)
        {
            var values = value.Split(',');
            var newValues = values[0].ToLowerInvariant();
            return newValues == "true";
        }

        private static int ExtractId(string Id)
        {
            var values = Id.Split('.');
            var id = values[1];
            int converted;
            if (Int32.TryParse(id, out converted))
                return converted;
            else
                throw new InvalidCastException("the Id wasn't an Int");
        }

        private void Validate(Volunteer volunteer, List<JobRole> jobRoles, List<Technology> technologies)
        {
            if (String.IsNullOrEmpty(volunteer.FirstName))
                ModelState.AddModelError("FirstName", "First Name is Required");

            if (!String.IsNullOrEmpty(volunteer.FirstName))
            {
                if (volunteer.FirstName.Length > 30)
                    ModelState.AddModelError("FirstName", "First name cannot exceed 30 characters");
            }

            if (String.IsNullOrEmpty(volunteer.LastName))
                ModelState.AddModelError("LastName", "Last Name is Required");

            if (!String.IsNullOrEmpty(volunteer.LastName))
            {
                if (volunteer.LastName.Length > 30)
                    ModelState.AddModelError("LastName", "Last name cannot exceed 30 characters");
            }

            if (String.IsNullOrEmpty(volunteer.EmailAddress))
                ModelState.AddModelError("EmailAddress", "Email Address is Required");

            if (!String.IsNullOrEmpty(volunteer.TeamName))
            {
                if (volunteer.TeamName.Length > 30)
                    ModelState.AddModelError("TeamName", "Team Name cannot exceed 30 characters");
            }

            if (!String.IsNullOrEmpty(volunteer.EmailAddress))
            {
                if (volunteer.EmailAddress.Length > 255)
                    ModelState.AddModelError("EmailAddress", "Email Address cannot exceed 250 characters");
            }

            if (String.IsNullOrEmpty(volunteer.PhoneNumber))
                ModelState.AddModelError("PhoneNumber", "Phone Number is Required");

            if (!String.IsNullOrEmpty(volunteer.PhoneNumber))
            {
                if (volunteer.PhoneNumber.Length > 50)
                    ModelState.AddModelError("PhoneNumber", "Phone Number cannot exceed 50 characters");
            }

            if (jobRoles == null || jobRoles.Count == 0)
                ModelState.AddModelError("Roles", "You have to enter at least one role");

            if (String.IsNullOrEmpty(volunteer.JobDescription))
                ModelState.AddModelError("JobDescription", "Day job is Required");

            if (!String.IsNullOrEmpty(volunteer.JobDescription))
            {
                if (volunteer.JobDescription.Length > 100)
                    ModelState.AddModelError("JobDescription", "Day job cannot exceed 100 characters");
            }

            if (technologies == null || technologies.Count == 0)
                ModelState.AddModelError("Technologies", "You have to enter at least one technology");

            if (volunteer.YearsOfExperience == null)
                ModelState.AddModelError("YearsOfExperience", "Years of Experience is required");
            if (!String.IsNullOrEmpty(volunteer.DietaryNeeds))
            {
                if (volunteer.DietaryNeeds.Length > 50)
                    ModelState.AddModelError("DietaryNeeds", "Dietary needs cannot exceed 50 characters");
            }

            if (!String.IsNullOrEmpty(volunteer.TwitterHandle))
            {
                if (volunteer.TwitterHandle.Length > 50)
                    ModelState.AddModelError("TwitterHandle", "Twitter handle cannot exceed 50 characters");
            }

            if (!String.IsNullOrEmpty(volunteer.Bio))
            {
                if (volunteer.Bio.Length > 4000)
                    ModelState.AddModelError("Bio", "Bio cannot exceed 4000 characters");
            }

            if (!String.IsNullOrEmpty(volunteer.Comments))
            {
                if (volunteer.Comments.Length > 4000)
                    ModelState.AddModelError("Comments", "Comments cannot exceed 4000 characters");
            }
        }
    }

    public class SignUpViewModel
    {
        public Volunteer Volunteer;
        public SelectList Experience;
        public SelectList Technologies;
        public SelectList ShirtSizes;
        public SelectList ShirtStyles;
        public SelectList JobRoles;

        private LookupRepository lookupRepository = new LookupRepository();

        public SignUpViewModel()
        {
            Construct(null);
        }

        public SignUpViewModel(Volunteer volunteer)
        {
            Construct(volunteer);
        }

        private void Construct(Volunteer volunteer)
        {
            if (volunteer == null)
                Volunteer = new Volunteer();
            else
                Volunteer = volunteer;

            JobRoles = GetJobRoles();
            ShirtSizes = GetShirtSizes();
            ShirtStyles = GetShirtStyles();
            Experience = GetExperienceLevels();
            Technologies = GetTechnologies();
        }

        private SelectList GetJobRoles()
        {
            var roles = lookupRepository.GetAllJobRoles();
            return new SelectList(roles, "JobRoleID", "Description");
        }

        private SelectList GetTechnologies()
        {
            var technologies = lookupRepository.GetAllTechnologies();
            return new SelectList(technologies, "TechnologyID", "Description");
        }

        private SelectList GetShirtSizes()
        {
            var sizes = new List<SelectListItem>()
                            {
                                new SelectListItem {Text = "", Value = ""},
                                new SelectListItem {Text = "S", Value = "S"},
                                new SelectListItem {Text = "M", Value = "M"},
                                new SelectListItem {Text = "L", Value = "L"},
                                new SelectListItem {Text = "XL", Value = "XL"},
                                new SelectListItem {Text = "2XL", Value = "2XL"},
                                new SelectListItem {Text = "3XL", Value = "3XL"}
                            };
            return new SelectList(sizes, "Text", "Value");
        }

        private SelectList GetShirtStyles()
        {
            var styles = new List<SelectListItem>
                                  {
                                      new SelectListItem {Text = "", Value = ""},
                                      new SelectListItem {Text = "M", Value = "Mens"},
                                      new SelectListItem {Text = "W", Value = "Womens"}
                                  };
            return new SelectList(styles, "Text", "Value");
        }

        private SelectList GetExperienceLevels()
        {
            var levels = lookupRepository.GetAllExperienceLevels();
            return new SelectList(levels, "ExperienceLevelID", "Description");
        }
    }
}